﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace InternetSpiderLib
{
    public class DataBox
    {
        protected ReaderWriterLock RWLock = new ReaderWriterLock();

        /// <summary>
        /// 名称与实例的映射
        /// </summary>
        protected Dictionary<string, object> Name2Instance = new Dictionary<string, object>();

        /// <summary>
        /// 默认的Key
        /// </summary>
        private const string DEFAULT = "Default";

        public DataBox() { }

        public DataBox(DataBox data)
        {
            Name2Instance = new Dictionary<string, object>(data?.Name2Instance ?? new Dictionary<string, object>());
        }

        /// <summary>
        /// 设置默认实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance"></param>
        public DataBox Set<T>(T instance)
        {
            RWLock.Writer(() => { Set<T>(DEFAULT, instance); });
            return this;
        }

        /// <summary>
        /// 设置Key与实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="instance"></param>
        public DataBox Set<T>(string key, T instance)
        {
            RWLock.Writer(() =>
            {
                var format_key = GetFormatKey<T>(key);
                Name2Instance[format_key] = instance;
            });
            return this;
        }

        /// <summary>
        /// 获取默认实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Get<T>()
        {
            return RWLock.Reader(() => { return Get<T>(DEFAULT); });
        }

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <param name="key"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public object Get(string key, Type type)
        {
            return RWLock.Reader(() =>
            {
                var format_key = GetFormatKey(type, key);
                return Name2Instance[format_key];
            });
        }

        /// <summary>
        /// 根据Key获取对应实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return RWLock.Reader(() =>
            {
                var format_key = GetFormatKey<T>(key);
                if (Name2Instance.ContainsKey(format_key) == false)
                    return default(T);

                var obj = Name2Instance[format_key];

                if (obj is T)
                    return (T)obj;

                return default(T);
            });
        }

        /// <summary>
        /// 格式化的Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        protected string GetFormatKey<T>(string key)
        {
            return GetFormatKey(typeof(T), key);
        }

        /// <summary>
        /// 格式化的Key
        /// </summary>
        /// <param name="type"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        protected string GetFormatKey(Type type, string key)
        {
            return $"{type.FullName}::{key}";
        }
    }
}
